/*! \file AVRcommon.h
*	\brief AVR Common File for all libraries
*	\author:	SJValley Engineering - Contact:	support@sjvalley.com
*	\ingroup 	SJVECOMMON
*/
#ifndef _SJVALLEY_FRAMEWORK_COMMON
#define _SJVALLEY_FRAMEWORK_COMMON

//! TURN CODEVISION to 1 if you are using CodeVision, leave it 0 for GCC/Winavr
#define CODEVISION 		0

#if(CODEVISION)
	#warning "Define CodeVision CPU File here! ie: #include <mega324.h>"
	#include <delay.h>
	#error "SYSTEM_CLOCK not defined, define it at AVRcommon.h"
	//#define SYSTEM_CLOCK	18432000
#else
	#ifndef F_CPU
	#warning "F_CPU not defined for CPU under Project Configuration!  Uart & Delay won't work!"
	#define F_CPU 18432000
	#endif
	#include <avr/io.h>
	#include <util/delay.h>
	#include <avr/interrupt.h>
	#define delay_us(x)	_delay_us(x)	///< delay in micro-seconds.  Works up to CPU Clock/768 (uS)
	#define delay_ms(x)	_delay_ms(x)	///< delay in milli-seconds.  Works accurately up to CPU Clock/768 (ms)
	#define SYSTEM_CLOCK	F_CPU		///< SYSTEM_CLOCK is derived for Project's CPU Clock
#endif

#define GLOBAL_INTERRUPTS_ENABLED()		(SREG & 0x80)

#define SYSTEM_CLOCK_MHZ	(SYSTEM_CLOCK/1000000.0f)

//! Generic bit-type pointer to access individual bits of IO memory or variable
//! Example:
//!	@code
//!	declareBitType(myLed, PORTA); // myLed becomes pointer to PORTA
//!	myLed->b0 = 1;                // Turn  on single bit on PORTA
//!	myLed->b7 = 0;                // Turn off single bit on PORTA
//!	@endcode
typedef union bitType
{
  struct {
	char b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; /* Individual Bit Value (read/write) */
  };
  char value; /* 8-bit Value */
}bitType;

//! Provides easy way to declare a bit structure
#define declareBitType(name, source)	\
volatile bitType *name = (bitType*)(&source);

//! Gets lower 8 bits of a 16-bit data type
#define getUpper8Bits(myInt)                    (unsigned char)(myInt >> 8)
//! Gets upper 8 bits of a 16-bit data type
#define getLower8Bits(myInt)                    (unsigned char)(myInt)
//! Combines two bytes into a single 16-bit data type
#define combineCharsToInt(highchar, lowchar)    ((((unsigned int)highchar)<<8) | lowchar)

//! @name General definitions of bit positions
//@{
#define ALL_BITS                0xff
#define BIT0                    0x01
#define BIT1                    0x02
#define BIT2                    0x04
#define BIT3                    0x08
#define BIT4                    0x10
#define BIT5                    0x20
#define BIT6                    0x40
#define BIT7                    0x80
//@}

//! @name Following Macros can be used to manipulate bits easily:
//! Example:
//!	@code
//!	setBit(PORTA, BIT0);
//!	unsetBit(DDRB, BIT6);
//!	toggleBit(PORTC, ALL_BITS);
//!	@endcode
//@{
#define setBit(dest,theBit)          dest |= theBit
#define unsetBit(dest,theBit)        dest &= (char)()~theBit);
#define toggleBit(dest,theBit)       dest ^= theBit;
//@}

//! @name Following Macros to find out if a bit is set or unset
//! @code
//!	if(bitIsSet(PORTA, BIT0))
//!	if(bitIsClear(PORTA, BIT0))
//! @endcode
//@{
#define bitIsSet(source,theBit)		  (source&theBit)
#define bitIsClear(source,theBit)	  (!bitIsSet(source, theBit))
//@}

//! Typedef for a void function pointer taking no parameters
typedef void (*FuncPointer)(void);

//! Typedef for a void function pointer with int, and function pointer as argument
typedef void (*FuncPointerIntFun)(int s, FuncPointer fun);

//! Typedef for a void function pointer with int, int, and function pointer as argument
typedef void (*FuncPointerIntIntFun)(int s, int select, FuncPointer fun);

//! Typedef for a void function pointer with an integer parameter
typedef void (*FuncPointerInt)(int s);

//! Typedef for a function pointer that returns a char and takes int as parameter
typedef char (*FuncPointerReturnChar)(int s);

//! Structure to access a Port's direction, output, and input more intuitively
//!	@code
//!	porta.direction.b0 = 1;
//!	porta.output.b0 = 1;
//!	if(porta.input.value == 0x55)
//!	@endcode
typedef struct portPinStruct
{
	union
	{
	  struct {
		char b0:1;	///< Bit0 of this PORT's Input
		char b1:1;	///< Bit0 of this PORT's Input
		char b2:1;	///< Bit0 of this PORT's Input
		char b3:1;	///< Bit0 of this PORT's Input
		char b4:1;	///< Bit0 of this PORT's Input
		char b5:1;	///< Bit0 of this PORT's Input
		char b6:1;	///< Bit0 of this PORT's Input
		char b7:1;	///< Bit0 of this PORT's Input
	  };
	  char value;	///< 8-bit value of this PORT's Input
	}input;
	union
	{
		struct {
			char b0:1;	///< Bit0 of this PORT's Direction
			char b1:1;	///< Bit0 of this PORT's Direction
			char b2:1;	///< Bit0 of this PORT's Direction
			char b3:1;	///< Bit0 of this PORT's Direction
			char b4:1;	///< Bit0 of this PORT's Direction
			char b5:1;	///< Bit0 of this PORT's Direction
			char b6:1;	///< Bit0 of this PORT's Direction
			char b7:1;	///< Bit0 of this PORT's Direction
		  };
		  char value;	///< 8-bit value of this PORT's Direction
	}direction;
	union
	{
		struct {
			char b0:1;	///< Bit0 of this PORT's Output
			char b1:1;	///< Bit0 of this PORT's Output
			char b2:1;	///< Bit0 of this PORT's Output
			char b3:1;	///< Bit0 of this PORT's Output
			char b4:1;	///< Bit0 of this PORT's Output
			char b5:1;	///< Bit0 of this PORT's Output
			char b6:1;	///< Bit0 of this PORT's Output
			char b7:1;	///< Bit0 of this PORT's Output
		  };
		  char value;	///< 8-bit value of this PORT's Output
	}output;
}portPinStruct;


//! @name General definitions of "port" with member variables:
//! porta.direction.value  porta.output.b0  porta.input.b1 etc.
///@{
#ifdef PORTA
#define porta    (*(portPinStruct *) &PINA)
#endif
#ifdef PORTB
#define portb    (*(portPinStruct *) &PINB)
#endif
#ifdef PORTC
#define portc    (*(portPinStruct *) &PINC)
#endif
#ifdef PORTD
#define portd    (*(portPinStruct *) &PIND)
#endif
#ifdef PORTE
#define porte    (*(portPinStruct *) &PINE)
#endif
#ifdef PORTF
#define portf    (*(portPinStruct *) &PINF)
#endif
#ifdef PORTG
#define portg    (*(portPinStruct *) &PING)
#endif
#ifdef PORTH
#define porth    (*(portPinStruct *) &PINH)
#endif
#ifdef PORTI
#define porti    (*(portPinStruct *) &PINI)
#endif
#ifdef PORTJ
#define portj    (*(portPinStruct *) &PINJ)
#endif
#ifdef PORTK
#define portk    (*(portPinStruct *) &PINK)
#endif
#ifdef PORTL
#define portl    (*(portPinStruct *) &PINL)
#endif
///@}

//! Easy way to manage bytes and ints 8/16bit
//! @code
//!	wordStruct a;
//!	a.word = 0x1122;
//!	char lowByte = a.byte.low;
//!	char highByte= a.byte.high;
//! @endcode
typedef union wordStruct
{
	unsigned int word;
	struct {
		unsigned char low;
		unsigned char high;
	}byte;
}wordStruct;

//! Queue Structure
typedef struct queueStruct
{
	int writePtr;
	int readPtr;
	volatile int count;
}queueStruct;




//! Pin Change Mask Register.
/// pcicr register has s_pcicr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: pcicr.pcie0 = 1;
typedef union s_pcicr
{
	struct {
		char pcie0:1;
		char pcie1:1;
		char pcie2:1;
		char pcie3:1;
	};
	char value;
}s_pcicr;
#ifdef PCICR
#define pcicr    (*(s_pcicr *) &PCICR)
#endif

//! Pin Change Flag Register.
/// pcifr register has s_pcifr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: pcifr.pcie = 0;
typedef union s_pcifr
{
	struct {
		char pcie0:1;
		char pcie1:1;
		char pcie2:1;
		char pcie3:1;
	};
	char value;
}s_pcifr;
#ifdef PCIFR
#define pcifr    (*(s_pcifr *) &PCIFR)
#endif

//! Register that shows how the Chip was reset.
/// mcusr register has s_mcusr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: if(mcusr.powerOnResetFlag == 1) ...
typedef union s_mcusr
{
	struct {
		char powerOnResetFlag:1;
		char externalResetFlag:1;
		char brownOutResetFlag:1;
		char watchdogResetFlag:1;
		char jtagResetFlag:1;
	};
	char value;
}s_mcusr;
#ifdef MCUSR
#define mcusr    (*(s_mcusr *) &MCUSR)
#endif

//! Analog-To-Digital Control Register to operate the ADC.
/// adcsra register has s_adcsra bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: adcsra.enable = 1;
typedef union s_adcsra
{
	struct {
		char prescalar3bits:3;	///< 0=CLK/2, 1=CLK/2, 2=CLK/4, 3=CLK/8, 4=CLK/16, 5=CLK/32, 6=CLK/64, 7=CLK/128 */
		char interruptEnable:1;
		char interruptFlag:1;
		char autoTriggerEnable:1;
		char startConversion:1;
		char enable:1;
	};
	char value; /* 8-bit Value */
}s_adcsra;
#ifdef ADCSRA
#define adcsra    (*(s_adcsra *) &ADCSRA)
#endif

//! Analog-To-Digital Control Register for channel select and ADC reference select.
/// admux register has s_admux bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: admux.mux5bit = 5;
typedef union s_admux
{
	struct {
		char mux5bit:5;
		char leftAdjust:1;
		char adcReference:2;
	};
	char value; /* 8-bit Value */
}s_admux;
#ifdef ADMUX
#define admux    (*(s_admux *) &ADMUX)
#endif

//! Analog-To-Digital Control Register for auto-trigger configuration.
/// adcsrb register has s_adcsrb bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: adcsrb.autoTriggerSource = 3;
typedef union s_adcsrb
{
	struct {
		char autoTriggerSource:3;
		#ifdef MUX5
		char mux5:1;		///< If set to one, then selects ADC Channel 8 & above based on mux[4:0] value at admux */
		#endif
	};
	char value; /* 8-bit Value */
}s_adcsrb;
#ifdef ADCSRB
#define adcsrb    (*(s_adcsrb *) &ADCSRB)
#endif





//! External Interrupt Configuration Register A (INT0 - INT3).
/// eicra register has s_eicra bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: eicra.int0Mode = 2;
typedef union s_eicra
{
	struct {
		char int0Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		char int1Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		char int2Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		#ifdef ISC31		// ISC31 not available for some CPUs */
		char int3Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		#endif
	};
	char value; /* 8-bit Value */
}s_eicra;
#if defined (EICRA)
#define eicra    (*(s_eicra *) &EICRA)
#endif

//! External Interrupt Configuration Register (INT4 - INT7).
/// eicrb register has s_eicrb bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: eicrb.int4Mode = 3;
typedef union s_eicrb
{
	struct {
		char int4Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		char int5Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		char int6Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
		char int7Mode:2;	///< 0=Low level, 1=Any Edge, 2=Falling Edge, 3=Rising Edge */
	};
	char value; /* 8-bit Value */
}s_eicrb;
#if defined (EICRB)
#define eicrb    (*(s_eicrb *) &EICRB)
#endif

//! External Interrupt Enable Register.
/// eimsk register has s_eimsk bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: eimsk.int0Enable = 1;
typedef union s_eimsk
{
	struct {
		char int0Enable:1;
		char int1Enable:1;
		char int2Enable:1;
		#ifdef INT3	// Take it for granted that if INT3 is defined, then INT3-INT7 are available
		char int3Enable:1;
		char int4Enable:1;
		char int5Enable:1;
		char int6Enable:1;
		char int7Enable:1;
		#endif
	};
	char value; /* 8-bit Value */
}s_eimsk;
#if defined (EIMSK)
#define eimsk    (*(s_eimsk *) &EIMSK)
#endif

//! External Interrupt Flag and Acknowledge Register.
/// eifr register has s_eifr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: eifr.int0Acknowledge = 1;
typedef union s_eifr
{
	struct {
		char int0Acknowledge:1;
		char int1Acknowledge:1;
		char int2Acknowledge:1;
		#ifdef INT3	// Take it for granted that if INT3 is defined, then INT3-INT7 are available
		char int3Acknowledge:1;
		char int4Acknowledge:1;
		char int5Acknowledge:1;
		char int6Acknowledge:1;
		char int7Acknowledge:1;
		#endif
	};
	char value; /* 8-bit Value */
}s_eifr;
#if defined (EIFR)
#define eifr    (*(s_eifr *) &EIFR)
#endif

//! SPI Control Register 1.
/// spcr register has s_spcr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: spcr.masterMode = 1;
typedef union s_spcr
{
	struct {
		char clockDivider:2;	///< 0 = CLK/4, 1=CLK/16, 2=CLK/64, 3=CLK/128, @see spsr.spiDoubleClockSpeed for 4 more speed levels */
		char clockPhaseSampleOnRisingEdge:1;
		char clockPolarityLatchOnFallingEdge:1;
		char masterMode:1;
		char dataOrderLSBFirst:1;
		char spiEnable:1;
		char interruptEnable:1;
	};
	char value; /* 8-bit Value */
}s_spcr;
#if defined (SPCR)
#define spcr    (*(s_spcr *) &SPCR)
#endif

//! SPI Control Register 2.
/// spsr register has s_spsr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: spsr.spiInterruptFlag = 1;
typedef union s_spsr
{
	struct {
		char spiDoubleClockSpeed:1;
		char reserved:5;
		char writeCollisionFlag:1;
		char spiInterruptFlag:1;
	};
	char value; /* 8-bit Value */
}s_spsr;
#if defined (SPSR)
#define spsr    (*(s_spsr *) &SPSR)
#endif

//! UART Status and Configuration Register.
/// ucsr0a register has s_ucsrXa bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: ucsr0a.rxComplete = 1;
typedef union s_ucsrXa
{
	struct {
		char multiCPUMode:1;
		char doubleSpeed:1;
		char parityError:1;
		char dataOverRunError:1;
		char frameError:1;
		char txRegisterEmpty:1;
		char txComplete:1;
		char rxComplete:1;
	};
	char value; /* 8-bit Value */
}s_ucsrXa;
#if defined (UCSRA)
#define ucsr0a    (*(s_ucsrXa *) &UCSRA)
#elif defined (UCSR0A)
#define ucsr0a    (*(s_ucsrXa *) &UCSR0A)
#endif
#if defined (UCSR1A)
#define ucsr1a    (*(s_ucsrXa *) &UCSR1A)
#endif
#if defined (UCSR2A)
#define ucsr2a    (*(s_ucsrXa *) &UCSR2A)
#endif
#if defined (UCSR3A)
#define ucsr3a    (*(s_ucsrXa *) &UCSR3A)
#endif

//! Uart Configuration Register for Mode & Interrupts.
/// ucsr0b register has s_ucsrXb bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: ucsr0b.rxEnable = 1;
typedef union s_ucsrXb
{
	struct {
		char txBit9In9bitMode:1;
		char rxBit9In9bitMode:1;
		char characterSizeBit2:1;	///< see ucsrXc.frameFormat */
		char txEnable:1;
		char rxEnable:1;
		char txDataEmptyInterruptEnable:1;
		char txCompleteInterruptEnable:1;
		char rxCompleteInterruptEnable:1;
	};

	char value; /* 8-bit Value */
}s_ucsrXb;
#if defined (UCSRB)
#define ucsr0b    (*(s_ucsrXb *) &UCSRB)
#elif defined (UCSR0B)
#define ucsr0b    (*(s_ucsrXb *) &UCSR0B)
#endif
#if defined (UCSR1B)
#define ucsr1b    (*(s_ucsrXb *) &UCSR1B)
#endif
#if defined (UCSR2B)
#define ucsr2b    (*(s_ucsrXb *) &UCSR2B)
#endif
#if defined (UCSR3B)
#define ucsr3b    (*(s_ucsrXb *) &UCSR3B)
#endif

//! Uart Mode and Frame Configuration Register.
/// ucsr0c register has s_ucsrXc bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: ucsr0c.stopBits = 1;
typedef union s_ucsrXc
{
	struct {
		char syncModeClockPolarity:1; ///< 0 - Data changed at rising edge, 1- Data changed at falling edge */
		char frameFormat:2;	///< Combine with ucsrXb.characterSizeBit2: 0=5bit, 1=6bit, 2=7bit, 3=8bit, 7=9bit */
		char stopBits:1;	///< 0=1-bit, 1=2-bit */
		char parityMode:2;	///< 0=Disabled, 1=Reserved, 2=Even, 3=Odd */
		char modeSelect:2;	///< 0=Async, 1=Sync, 2=Reserved, 3=Master SPI */
	};

	char value; /* 8-bit Value */
}s_ucsrXc;
#if defined (UCSRC)
#define ucsr0c    (*(s_ucsrXc *) &UCSRC)
#elif defined (UCSR0C)
#define ucsr0c    (*(s_ucsrXc *) &UCSR0C)
#endif
#if defined (UCSR1C)
#define ucsr1c    (*(s_ucsrXc *) &UCSR1C)
#endif
#if defined (UCSR2C)
#define ucsr2c    (*(s_ucsrXc *) &UCSR2C)
#endif
#if defined (UCSR3C)
#define ucsr3c    (*(s_ucsrXc *) &UCSR3C)
#endif

//! I2C Control Register.
/// twcr register has s_twcr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: twcr.twiEnable = 1;
typedef union s_twcr
{
	struct {
		char interruptEnable:1;
		char reserved:1;
		char twiEnable:1;
		char twiWriteCollisonFlag:1;
		char twiStop:1;
		char twiStart:1;
		char twiEnableAcknowledge:1;
		char interruptFlag:1;
	};
	char value; /* 8-bit Value */
}s_twcr;
#if defined(TWCR)
#define twcr    (*(s_twcr *) &TWCR)
#endif

//! I2C Prescalar and Status Register.
/// twsr register has s_twsr bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: twsr.twiPrescalar = 2;
typedef union s_twsr
{
	struct {
		char twiStatus:5;		///< See datasheet for status information */
		char reserved:1;
		char twiPrescalar:2;	///< 0=CLK/1, 1=CLK/4, 2=CLK/8, 3=CLK/64 */
	};

	char value; /* 8-bit Value */
}s_twsr;
#if defined(TWCR)
#define twsr    (*(s_twsr *) &TWSR)
#endif





//! Timer0 Control Register for output & mode.
/// tccr0a register has s_tccr0a bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr0a.modeBit10 = 2;
typedef union s_tccr0a
{
	struct {
		char modeBit10:2;	///< @see with tccr0b.modeBit2 See datasheet for mode Info */
		char reserved:2;
		char oc0BOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
		char oc0AOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
	};
	char value;
}s_tccr0a;
#if defined(TCCR0A)
#define tccr0a    (*(s_tccr0a *) &TCCR0A)
#endif

//! Timer0 Prescalar & Mode Configuration.
/// tccr0b register has s_tccr0b bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr0b.preScalar = 2;
typedef union s_tccr0b
{
	struct {
		char preScalar:3;	///< 0=Stop, 1=CLK/8, 2=CLK/64, 3=CLK/256, 4=CLK/1024, 5,6=External Clock on T0(see datasheet) */
		char modeBit2:1;
		char reserved:4;
	};
	char value;
}s_tccr0b;
#if defined(TCCR0B)
#define tccr0b    (*(s_tccr0b *) &TCCR0B)
#endif

//! Timer0 Interrupt Configuration Register.
/// timsk0 register has s_timsk0 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: timsk0.overFlowInterruptEnable = 1;
typedef union s_timsk0
{
	struct {
		char overFlowInterruptEnable:1;
		char oc0aMatchInterruptEnable:1;
		char oc0bMatchInterruptEnable:1;
		char reserved:5;
	};
	char value;
}s_timsk0;
#if defined(TIMSK0)
#define timsk0    (*(s_timsk0 *) &TIMSK0)
#endif

//! Timer0 Interrupt Flag & Acknowledge Register.
/// tifr0 register has s_tifr0 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tifr0.overFlowInterruptFlag = 1;
typedef union s_tifr0
{
	struct {
		char overFlowInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc0aMatchInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc0bMatchInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char reserved:5;
	};
	char value;
}s_tifr0;
#if defined(TIFR0)
#define tifr0    (*(s_tifr0 *) &TIFR0)
#endif





//! Timer1 Control Register for output & mode.
/// tccr1a register has s_tccr1a bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr1a.wgm_mode10 = 2;
typedef union s_tccr1a
{
	struct {
		char wgm_mode10:2;		///< 2/4 bits to control Wave-form generate mode.  See datasheet more more info */
		#ifdef COM1C1
		char ocxCOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
		#else
		char reserved:2;
		#endif
		char ocxBOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
		char ocxAOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
	};
	char value;
}s_tccr1a;
#if defined(TCCR1A)
#define tccr1a    (*(s_tccr1a *) &TCCR1A)
#endif
#if defined(TCCR3A)
#define tccr3a    (*(s_tccr3a *) &TCCR3A)
#endif
#if defined(TCCR4A)
#define tccr4a    (*(s_tccr3a *) &TCCR3A)
#endif
#if defined(TCCR5A)
#define tccr5a    (*(s_tccr3a *) &TCCR3A)
#endif

//! Timer1 Control Register for mode & prescalar.
/// tccr1b register has s_tccr1b bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr1b.preScalar = 3;
typedef union s_tccr1b
{
	struct {
		char preScalar:3;	///< 0=Stop, 1=CLK/1, 2=CLK/8, 3=CLK/64, 4=CLK/256, 5=CLK/1024, 6=External (Tn pin) falling edge, 7=External, rising edge*/
		char wgm_mode32:2;	///< 2/4 bits to control Wave-form generate mode.  See datasheet for more info */
		char reserved:1;
		char inputCaptureEdgeSelect:1;
		char inputCaptureNoiseCanceler:1;
	};
	char value;
}s_tccr1b;
#if defined(TCCR1B)
#define tccr1b    (*(s_tccr1b *) &TCCR1B)
#endif
#if defined(TCCR3B)
#define tccr3b    (*(s_tccr1b *) &TCCR3B)
#endif
#if defined(TCCR4B)
#define tccr4b    (*(s_tccr1b *) &TCCR4B)
#endif
#if defined(TCCR5B)
#define tccr5b    (*(s_tccr1b *) &TCCR5B)
#endif

//! Timer1 Interrupt Control Register.
/// timsk1 register has s_timsk1 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: timsk1.overFlowInterruptEnable = 1;
typedef union s_timsk1
{
	struct {
		char overFlowInterruptEnable:1;
		char ocxaMatchInterruptEnable:1;
		char ocxbMatchInterruptEnable:1;
		#ifdef OCIE1C
		char ocxcMatchInterruptEnable:1;
		char reserved1:1;
		#else
		char reserved1:2;
		#endif
		char inputCaptureInterruptEnable:1;
		char reserved2:2;
	};
	char value;
}s_timsk1;
#if defined(TIMSK1)
#define timsk1    (*(s_timsk1 *) &TIMSK1)
#endif
#if defined(TIMSK3)
#define timsk3    (*(s_timsk1 *) &TIMSK3)
#endif
#if defined(TIMSK4)
#define timsk4    (*(s_timsk1 *) &TIMSK4)
#endif
#if defined(TIMSK5)
#define timsk5    (*(s_timsk1 *) &TIMSK5)
#endif

//! Timer1 Interrupt Flag & Acknowledge Register.
/// tifr1 register has s_tifr1 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tifr1.overFlowInterruptFlag = 1 ;
typedef union s_tifr1
{
	struct {
		char overFlowInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc1aMatchInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc1bMatchInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		#ifdef OCF1C
		char oc1cMatchInterruptFlag:1;		///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char reserved1:1;
		#else
		char reserved1:2;
		#endif
		char inputCaptureInterruptFlag:1;	///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char reserved2:2;
	};
	char value;
}s_tifr1;
#if defined(TIFR1)
#define tifr1    (*(s_tifr1 *) &TIFR1)
#endif






//! Timer2 Control Register for output & mode.
/// tccr2a register has s_tccr2a bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr2a.modeBit10 = 2;
typedef union s_tccr2a
{
	struct {
		char modeBit10:2;	///< @see with tccr2b.modeBit2 See datasheet for mode Info */
		char reserved:2;
		char oc2BOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
		char oc2AOutputMode:2;	///< Usually: 0=Disconnected, 1=Toggle on match, 2=Clear on match, 3=Set on match */
	};
	char value;
}s_tccr2a;
#if defined(TCCR2A)
#define tccr2a    (*(s_tccr2a *) &TCCR2A)
#endif

//! Timer2 Prescalar & Mode Register.
/// tccr2b register has s_tccr2b bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tccr2b.preScalar = 3;
typedef union s_tccr2b
{
	struct {
		char preScalar:3;	///< 0=Stop, 1=CLK/1, 2=CLK/8, 3=CLK/32, 4=CLK/64, 5=CLK/128, 6=CLK/256, 7=CLK/1024*/
		char modeBit2:1;
		char reserved:4;
	};
	char value;
}s_tccr2b;
#if defined(TCCR2B)
#define tccr2b    (*(s_tccr2b *) &TCCR2B)
#endif

//! Timer2 Interrupt Control Register.
/// timsk2 register has s_timsk2 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: timsk2.overFlowInterruptEnable =1 ;
typedef union s_timsk2
{
	struct {
		char overFlowInterruptEnable:1;
		char oc2aMatchInterruptEnable:1;
		char oc2bMatchInterruptEnable:1;
		char reserved:5;
	};
	char value;
}s_timsk2;
#if defined(TIMSK2)
#define timsk2    (*(s_timsk2 *) &TIMSK2)
#endif

//! Timer2 Interrupt Flag & Acknowledge Register.
/// tifr2 register has s_tifr2 bit-members that can be read or written.
/// Not all CPUs has this register defined.
/// \note Usage: tifr2.overFlowInterruptFlag = 1;
typedef union s_tifr2
{
	struct {
		char overFlowInterruptFlag:1;	///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc2aMatchInterruptFlag:1;	///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char oc2bMatchInterruptFlag:1;	///< 1=Interrupt, Write 1 to acknowledge interrupt */
		char reserved:5;
	};
	char value;
}s_tifr2;
#if defined(TIFR2)
#define tifr2    (*(s_tifr2 *) &TIFR2)
#endif


/// Concatenates two words together at compile time
#define _MACRO_CONCATENATE(a,b)	a##b

/// @name Uses _MACRO_CONCATENATE to access PORT, DDR, and PIN value.
/// This can be used for a user to provide any port value
/// and your file can access the ports DDR, PIN and PORT registers
/// without having the user to define DDR, PIN and PORT.
///	Example, if you define B, then you can access DDRB, PORTB, and PINB
/// using DDRi(B), PORTi(B), and PINi(B)
//@{
#define PINi(x)					_MACRO_CONCATENATE(PIN, x)
#define DDRi(x)					_MACRO_CONCATENATE(DDR, x)
#define PORTi(x)				_MACRO_CONCATENATE(PORT, x)
//@}


//! Error types used by various library files
typedef enum {
                // General error/success codes
                 _SUCCESS=0, _E_INVALID_TIMER=1, _E_INVALID_POINTER=2,

				// Timer functions error codes
                 _E_REPEAT_COUNT_TOO_BIG=10, _E_REPEAT_COUNT_INVALID=11, _E_REPEAT_TIME_CANNOT_BE_LESS_THAN_1000us=12,
                 _E_REPEAT_TIME_CANNOT_BE_GREATER_THAN_6500MS=13, _E_INT_INTERVAL_EXCEEDS_MAXIMUM_POSSIBLE=15,
                 _E_REPEAT_TIME_CANNOT_BE_LESS_THAN_20US_DUE_TO_ISR_TIME_OVERHEAD=16,
                 _E_OUT_OF_SLOTS=17, _E_NOT_ACTIVE_OR_NOT_FOUND=18, _E_ALREADY_ADDED_CANNOT_ADD_DUPLICATE=19,

                 // serial error codes
                 _E_INVALID_BAUD_RATE=31, _E_NO_SERIAL_DATA=32, _E_RX_AUTO_CONFIG_ERROR=33,

                 // interrupt configuration error codes
                 _E_INVALID_INTERRUPT_OR_INT_SET_TO_FALSE_IN_HEADER_FILE=40, _E_INVALID_INTERRUPT_CONFIGURATION=41, _E_FUNCTION_POINTER_IS_INVALID=42,

                 // ADC error codes
                 _ADC_INIT_ERROR_WRONG_REFERENCE_TYPE=51, _ADC_INIT_ERROR_INVALID_SPEED=52
             } ENUM_RESULT;

//! @name defines _TIMER0, _TIMER1 and _TIMER2 used by some libraries.
//@{
#define _TIMER0 0x20
#define _TIMER1 0x40
#define _TIMER2 0x80
//@}


#if(CODEVISION)
	#define ENABLE_INTERRUPTS       #asm("sei")
	#define DISABLE_INTERRUPTS      #asm("cli")
	#ifndef bool
		#define bool	bit
	#endif
#else
	//! Disables global interrupts
	#define ENABLE_INTERRUPTS       asm("sei")
	//! Enables global interrupts
	#define DISABLE_INTERRUPTS      asm("cli")
#endif

typedef enum { false=0, true=1} bool;
typedef enum { FALSE=0, TRUE=1} BOOL;

#ifndef null
//! Definition of null
    #define null    0
#endif
#ifndef NULL
//! Definition of NULL
    #define NULL    null
#endif

#ifndef u08
//! Definition of 8-bit unsigned type
#define u08 unsigned char
#endif

#ifndef uchar
//! Definition of uchar
#define uchar unsigned char
#endif

#ifndef u16
//! Definition of unsigned 16-bit data type
#define u16 unsigned int
#endif

#ifndef uint
//! Definition of uint
#define uint unsigned int
#endif

#ifndef ulong
//! Definition of ulong
#define ulong unsigned long
#endif

#endif

